#include "04_Acceptor.hpp"
#include <stdlib.h>     // exit函数
#include <sys/socket.h> //SOL_SOCKER

inline void error_msg(const char* msg = "", int ret_flag = -1)
{
    char buff[256] = {0};
    snprintf(buff, sizeof(buff), "%s | %d | %s : %s", __FILE__, __LINE__, __FILE__, msg);
    perror(buff);
}

namespace xy
{
Acceptor::Acceptor(unsigned short port, const std::string& ip)
    :_addr(port, ip)
    ,_sock()
    {
        SetReuseAddr(true);
        SetReusePort(true);
    }

int Acceptor::bind()
{
    int ret = ::bind(_sock.get_fd(), (const struct sockaddr*)_addr.get_InetAddress(), sizeof(_addr));
    if(ret < 0)
    {
        error_msg("bind");
    }
    return ret;
}

void Acceptor::listen()
{
    int ret = ::listen(_sock.get_fd(), 10000);
    if(ret < 0)
    {
        error_msg("listen");
    }
}

void Acceptor::SetReuseAddr(bool netflag)
{
    int flag = netflag;
    //SOL_SOCKET,套接字选项级别常量，操作的套接字层的选项，而非特定协议的选项
    int ret = setsockopt(_sock.get_fd(), SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
    if(ret < 0)
    {
        error_msg("reuse_addr");
    }
}

void Acceptor::SetReusePort(bool netflag)
{
    int flag = netflag;
    int ret = setsockopt(_sock.get_fd(), SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag));
    if(ret < 0)
    {
        error_msg("reuse_port");
    }
}

void Acceptor::ready()
{
    bind();
    listen();
}

int Acceptor::accept()
{
    int netfd = ::accept(_sock.get_fd(), nullptr, nullptr);
    //sockfd：监听套接字描述符（由 socket() 创建并经 bind()、listen() 配置）
    //addr：输出参数，用于存储客户端的地址信息（需预先分配内存）
    //addrlen：输入输出参数，传入时为 addr 缓冲区大小，返回时为实际地址长度
    if(netfd < 0)
    {
        error_msg("reuse_port");
    }

    return netfd;
}

int Acceptor::get_fd()
{
    return _sock.get_fd();
}

};
